﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    //源代码==》编译器==》解释器==》机器码
    //源代码根据语言的句法结构被编译器编译成对应的解释器语义树对象文件，然后调用解释器的根表达方法，将语义树解释成计算机可以执行的机器码。

    //终极表达式：不可以被分割的语句表达式
    //非终极表达式：由终极表达式组成的语句表达式
    internal class Program
    {
        static void Main(string[] args)
        {
            #region 脚本(源代码)
            /*
             * BEGIN               //脚本开始
             * MOVE 500,600;       //鼠标指针移动到目标位置(500,600)
             *  BEGIN LOOP 5       //开始循环5次
             *    LEFT_CLICK;      //循环体内单击左键
             *    DELAY 1;         //每次延迟1秒
             *  END;               //循环体结束
             * RIGHT_DOWN;         //按下右键
             * DELAY 7200;         //延迟2小时
             * END;                //脚本结束
             * **/
            #endregion 

            #region 分析并生成语义表达式树（将脚本翻译成语义表达式树,并生成对象存储到文件中,这个过程由编译器完成）

            #region 语义树分析
            //          ======》鼠标移动表达式
            //                   （Move）
            //                                                                ====》左键按下表达式
            //                                     ======》鼠标单击表达式            （LeftKeyDown）
            //表达式序列 ======》循环表达式                （LeftKeyClick）     ====》左键松开表达式
            //(Sequence)      (RepetExpression)                                     （LeftKeyUp）
            //                                     ======》系统延迟表达式            
            //                                            (Delay)
            //          ======》右键按下表达式
            //                (RightKeyDown)

            #endregion

            #region 生成语义表达式树对象
            //构造指令集语义树，实际情况这个构造过程会由编译器完成(Evaluator or Parser)
            Sequence sequence = new Sequence(new List<Expression>() {            
                new Move(new Point(500,600)),
                new RepetExpression(new Sequence(new List<Expression>(){               
                    new LeftKeyClick(),
                    new Delay(1)
                }),5),
                new RightKeyDown(),
                new Delay(7200)                     
            });
            #endregion

            #endregion

            #region 调用解释器的解释接口
            sequence.Interpret();
            #endregion 

            Console.ReadKey();
        }
    }

    #region 解释器
    public interface Expression
    {
        /// <summary>
        /// 解释
        /// </summary>
        void Interpret();
    }

    #region 终极表达式对象
    public class Move : Expression
    {
        Point MousePos;
        public Move(Point mousePos)
        {
            MousePos = mousePos;
        }

        public void Interpret()
        {
            Console.WriteLine("发送机器指令：移动鼠标到(" + MousePos.X + "," + MousePos.Y+")");
        }
    }

    public class LeftKeyDown : Expression
    {
        public void Interpret()
        {
            Console.WriteLine("发送机器指令:按下鼠标左键");
        }
    }

    public class LeftKeyUp : Expression
    {
        public void Interpret()
        {
            Console.WriteLine("发送机器指令:松开鼠标左键");
        }
    }
    public class RightKeyDown : Expression
    {
        public void Interpret()
        {
            Console.WriteLine("发送机器指令:按下鼠标右键");
        }
    }

    public class RightKeyUp : Expression
    {
        public void Interpret()
        {
            Console.WriteLine("发送机器指令:松开鼠标右键");
        }
    }

    public class Delay:Expression
    {
        private int seconds;
        public Delay(int seconds)
        {
            this.seconds = seconds;
        }
        public void Interpret()
        {
            Console.WriteLine("发送机器指令:延迟" + this.seconds.ToString() + "秒");
        }
    }
    #endregion

    #region 非终极表达式对象
    public class LeftKeyClick : Expression
    {
        Expression leftKeyDown;
        Expression leftKeyUp;
        public LeftKeyClick()
        {
            this.leftKeyUp = new LeftKeyUp();
            this.leftKeyDown = new LeftKeyDown();
        }
        public void Interpret()
        {
            this.leftKeyDown.Interpret();
            this.leftKeyUp.Interpret();
        }
    }
    public class RepetExpression:Expression
    {
        private Expression loopBodyExpression;
        private int loopCount;
        public RepetExpression(Expression loopBodyExpression, int loopCount)
        {
            this.loopBodyExpression = loopBodyExpression;
            this.loopCount = loopCount;
        }

        public void Interpret()
        {
            while(loopCount > 0)
            {
                loopBodyExpression.Interpret();
                loopCount--;
            }
        }
    }

    public class Sequence : Expression
    {
        private List<Expression> expressions;
        public Sequence (List<Expression> expressions)
        {
            this.expressions = expressions;
        }

        public void Interpret()
        {
            foreach (var item in expressions)
            {
                item.Interpret();
            }
        }
    }
    #endregion 
    #endregion

    //解释器模式起始就是组合模式的特殊应用，它巧妙地利用组合模式中的数据结构，基于上下文生成表达式(解释器)组合起来的语义树，最终通过逐级递进解释完成上下文的解析。
    //解释器模式还可以被应用于构建规则校验引擎,如将解释器接口Interpret()改成bool Validate(string target),并由各个实现类返回校验结果,类似于正则表达式校验引擎。
    //校验引擎根据正则表示生成校验语义树，同时将目标校验的字符串拆分,作为校验语义树的参数传入，然后调用校验器的接口Validate(string target)对目标校验字符串进行校验并返回校验结果
    


    //语言终究使文字的组合，如句子可以被拆分成为若干从句，从句进一步又可以被拆分为若干词、字，要解释语言就必须具备一套合理的拆分模式。
    //解释器模式完美地对各种表达式进行拆分、抽象、关系化与多态化，定义出一个完备的语法构建框架，最终通过表示式的组装与递归调用完成对目标语言的解释。
    //基于相似性的树形结构构建模型使系统具备良好的代码易读性与可维护性，灵活多态的表达式也是系统的可扩展性得到全面的提升。
}
